import { Asset } from 'cc';

type Loader<T> = (onProgress?: (percent: number) => void) => Promise<T>;

interface LoadOptions<T> {
    /** 加载器函数，需返回 Promise */
    loader: Loader<T>;
    /** 最大重试次数（默认 1） */
    maxRetries?: number;
    /** 是否刷新缓存 */
    forceRefresh?: boolean;
    /** 进度回调：0-1 */
    onProgress?: (percent: number) => void;
}

export class ResourceLoader<T> {
    private cache: T | null = null;
    private promise: Promise<T> | null = null;

    /** 加载资源（可缓存、可重试、可监听进度） */
    async load(options: LoadOptions<T>): Promise<T> {
        const {
            loader,
            maxRetries = 1,
            forceRefresh = false,
            onProgress,
        } = options;

        if (this.cache && !forceRefresh) {
            return this.cache;
        }

        // 如果已在加载中，返回同一个 Promise
        if (this.promise && !forceRefresh) {
            return this.promise;
        }

        let attempts = 0;

        const attemptLoad = async (): Promise<T> => {
            try {
                return await loader(onProgress);
            } catch (err) {
                if (++attempts < maxRetries) {
                    return attemptLoad(); // 递归重试
                } else {
                    throw err;
                }
            }
        };

        this.promise = attemptLoad()
            .then((res) => {
                this.cache = res;
                this.promise = null;
                return res;
            })
            .catch((err) => {
                this.promise = null; // 重置 Promise
                throw err;
            });

        return this.promise;
    }

    /** 清空缓存 */
    reset(): void {
        this.cache = null;
        this.promise = null;
    }

    /** 获取当前缓存资源 */
    get(): T | null {
        return this.cache;
    }
}

export const resourceLoader = new ResourceLoader<Asset>();
